﻿namespace MapleRock.P2PEmulator.Core
{
  using System;
  using System.Collections.Generic;
  using System.Diagnostics;
  using System.Linq;
  using System.Net;
  using System.Text;

  public sealed class NetworkState
  {
    private AdjacencyTable citiesAdjacency = null;

    private Dictionary<uint, City> cities = null;

    private Dictionary<uint, Peer> peers = null;

    private ulong uniqueId = 1;

    public NetworkState(
      Dictionary<uint, City> cities,
      AdjacencyTable citiesAdjacency,
      int dimensions,
      Dictionary<uint, Peer> peers,
      double udpDatagrammLossProbability)
    {
      Debug.Assert(null != cities, "null != cities");
      Debug.Assert(null != citiesAdjacency, "null != citiesAdjacency");
      Debug.Assert(null != peers, "null != peers");
      Debug.Assert(udpDatagrammLossProbability >= 0, "udpDatagrammLossProbability >= 0");
      Debug.Assert(udpDatagrammLossProbability <= 0.05, "udpDatagrammLossProbability <= 0.05");

      this.cities = cities;
      this.citiesAdjacency = citiesAdjacency;
      this.Dimensions = dimensions;
      this.peers = peers;

      this.FreePeers = new List<Peer>(peers.Values);

      this.ActivePeers = new HashSet<Peer>(peers.Values);

      this.Transport = new DataTransportEmulator();

      this.UdpDatagrammLossProbability = udpDatagrammLossProbability;

      this.Rand = new Random();
    }

    public uint TimePassedMs { get; private set; }

    public Dictionary<uint, City> Cities
    {
      get { return this.cities; }
    }

    public int Dimensions { get; private set; }

    public Dictionary<uint, Peer> Peers
    {
      get { return this.peers; }
    }

    public List<Peer> FreePeers { get; set; }

    public HashSet<Peer> ActivePeers { get; set; }

    public AdjacencyTable CitiesAdjacency
    {
      get { return this.citiesAdjacency; }
    }

    public Random Rand { get; private set; }

    public DataTransportEmulator Transport { get; set; }

    public double UdpDatagrammLossProbability { get; private set; }

    public ulong GenerateUniqueId()
    {
      return this.uniqueId++;
    }

    public void ResetTimer()
    {
      this.TimePassedMs = 0;
    }

    public void IncrementTimer(uint incrementMs)
    {
      Debug.Assert(incrementMs > 0, "incrementMs > 0");

      this.TimePassedMs += incrementMs;
    }
  }
}
